package com.zyh.cxf;

import com.xiaoleilu.hutool.util.StrUtil;
import com.zyh.dao.FundPayMapper;
import com.zyh.dao.KeyMapper;
import com.zyh.dao.TrandMapper;
import com.zyh.pojo.*;
import com.zyh.service.FundPayGroupService;
import com.zyh.util.RandomNumber;
import com.zyh.util.XstreamKit;
import com.zyh.util.safeutil.DESedeUtil;
import com.zyh.util.safeutil.SM2Utils;
import com.zyh.util.safeutil.Util;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author shihan
 * @date 2020-12-04-13:55
 */

@Component
public class FundPayOrderServiceImpl implements FundPayOrderService {

    @Autowired
    private TrandMapper trandMapper;

    @Autowired
    private FundPayMapper fundPayMapper;

    @Autowired
    private FundPayGroupService fundPayGroupService;

    @Autowired
    private KeyMapper keyMapper;

    @Override
    public String getFundPayOrder(String desXml) {
        Map<String, Object> keyMap = keyMapper.querykey();
        //查询加密的公钥
        String inencryptKey = (String) keyMap.get("PublicKey");
        String privateKey = (String) keyMap.get("PrivateKey");
        String plainText = "";
        //医保的入xml
        String innerXml = "";
        //返回的xml
        String retXml = "";
        //返回的加密xml
        String outDesXml = "";
        OutMessagePojo outMessagePojo = new OutMessagePojo();
        OutHeadPojo outHeadPojo = new OutHeadPojo();
        outHeadPojo.setIBSReturnCode("000000");

        outMessagePojo.setHead(outHeadPojo);

        OutBodyTransferPojo outBodyTransferPojo = new OutBodyTransferPojo();
        outMessagePojo.setOutBodyTransferPojo(outBodyTransferPojo);
        String serialNo = "";
        String reqTime = "";
        String unionBankNo = "";
        String interFaceNo = "";
        try {
            plainText = new String(SM2Utils.decrypt(Util.hexToByte(privateKey), Util.hexToByte(inencryptKey)));
            innerXml = DESedeUtil.decrypt(desXml, plainText);
            Document doc = DocumentHelper.parseText(innerXml);
            Element service = doc.getRootElement();
            String rtmCode = service.element("Body").elementText("Amount");
            unionBankNo = service.element("Body").elementText("UnionBankNo");
            serialNo = service.element("Head").elementText("serialNo");
            reqTime = service.element("Head").elementText("reqTime");
            outHeadPojo.setSerialNo(serialNo);

            if (unionBankNo != null && unionBankNo.length() == 12) {
                interFaceNo = "QRCB004";
            } else {
                interFaceNo = "QRCB003";
            }
            if (StrUtil.isBlank(rtmCode)) {
                outHeadPojo.setIBSReturnMsg("失败");
                outHeadPojo.setIBSJnlNo(RandomNumber.productBsnSrNo());

                outBodyTransferPojo.setOrderState("91");
                outBodyTransferPojo.setOrderFlowDescript("金额为空，请填写金额");

                retXml = XstreamKit.vo2Xml(outMessagePojo);
                outDesXml = DESedeUtil.encrypt(retXml, plainText);
                //日志落库
                logFellLibrary(interFaceNo, "", "", "91", "账号不符合", RandomNumber.productBsnSrNo(), "", "", "", "", XstreamKit.vo2Xml(outMessagePojo), innerXml);

                //将基金支付状态存库
                addTransactionStatus(interFaceNo, reqTime, serialNo, RandomNumber.productBsnSrNo(), "90", "转账失败--金额为空，请填写金额", "0");

                return outDesXml;
            } else {
                float amount = Float.valueOf(rtmCode);
                InMessage inMessage = XstreamKit.xml2Vo(innerXml, InMessage.class);
                TransferAccountsPojo pojo = inMessage.getBody();

                float payerAcNo = Float.valueOf(pojo.getPayerAcNo());
                float payeeAcNo = Float.valueOf(pojo.getPayeeAcNo());

                String id = trandMapper.queryAccNoById(pojo.getPayerAcNo());

                if (pojo.getPayerAcNo().length() != 17 || StrUtil.isBlank(id)) {
                    outHeadPojo.setIBSReturnMsg("失败");
                    outHeadPojo.setIBSJnlNo(RandomNumber.productBsnSrNo().substring(14, 32));

                    outBodyTransferPojo.setOrderState("91");
                    outBodyTransferPojo.setOrderFlowDescript("账号不合法请重新输入");
                    retXml = XstreamKit.vo2Xml(outMessagePojo);
                    outDesXml = DESedeUtil.encrypt(retXml, plainText);
                    //日志落库
                    logFellLibrary(interFaceNo, "", "", "91", "账号不符合", RandomNumber.productBsnSrNo(), "", "", "", "", XstreamKit.vo2Xml(outMessagePojo), innerXml);

                    //将基金支付状态存库
                    addTransactionStatus(interFaceNo, reqTime, serialNo, RandomNumber.productBsnSrNo(), "91", "转账失败--账号不合法请重新输入", "0");

                    return outDesXml;
                }
                //走业务流程
                retXml = fundPayGroupService.fundPayOrder(reqTime, serialNo, innerXml, outMessagePojo, pojo);

                outDesXml = DESedeUtil.encrypt(retXml, plainText);
                return outDesXml;
            }
        } catch (NumberFormatException e) {
            outHeadPojo.setIBSReturnMsg("失败");
            outHeadPojo.setIBSJnlNo(RandomNumber.productBsnSrNo());

            outBodyTransferPojo.setOrderState("91");
            outBodyTransferPojo.setOrderFlowDescript("金额或账号为空或包含特殊字符");

            retXml = XstreamKit.vo2Xml(outMessagePojo);
            try {
                outDesXml = DESedeUtil.encrypt(retXml, plainText);
                //日志落库
                logFellLibrary(interFaceNo, "", "", "91", "账号不符合", RandomNumber.productBsnSrNo(), "", "", "", "", XstreamKit.vo2Xml(outMessagePojo), innerXml);

                //将基金支付状态存库
                addTransactionStatus(interFaceNo, reqTime, serialNo, RandomNumber.productBsnSrNo(), "91", "转账失败--金额或账号包含特殊字符", "0");

                return outDesXml;
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try{
            if (StrUtil.isBlank(retXml)) {
                outHeadPojo.setIBSReturnMsg("失败");
                outHeadPojo.setIBSJnlNo(RandomNumber.productBsnSrNo().substring(14, 32));

                outBodyTransferPojo.setOrderState("91");
                outBodyTransferPojo.setOrderFlowDescript("转账失败--请检查密钥或网络");
                retXml = XstreamKit.vo2Xml(outMessagePojo);
                outDesXml = DESedeUtil.encrypt(retXml, plainText);
                //日志落库
                logFellLibrary(interFaceNo, "", "", "91", "请检查密钥或网络", RandomNumber.productBsnSrNo(), "", "", "", "", XstreamKit.vo2Xml(outMessagePojo), innerXml);

                //将基金支付状态存库
                addTransactionStatus(interFaceNo, reqTime, serialNo, RandomNumber.productBsnSrNo(), "91", "转账失败--请检查密钥或网络", "0");

                return outDesXml;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(retXml);
        System.out.println(outDesXml);
        return outDesXml;
    }

    /**
     * 基金支付状态存库
     */
    private void addTransactionStatus(String interFaceNo, String createTime, String serialNo, String bsnSrlNo, String status, String statusMessage, String isBig) {
        FundPayPoJo fundPayPoJo = new FundPayPoJo();
        fundPayPoJo.setINTERFACENO(interFaceNo);
        fundPayPoJo.setSerialNo(serialNo);
        fundPayPoJo.setBsnSrlNo(bsnSrlNo);
        fundPayPoJo.setStatus(status);
        fundPayPoJo.setStatusMessage(statusMessage);
        fundPayPoJo.setIsBig(isBig);
        fundPayPoJo.setCreateTime(createTime);
        //System.out.println(fundPayPoJo);
        fundPayMapper.addFund(fundPayPoJo);
    }

    /**
     * 日志落库
     */
    private void logFellLibrary(String interFaceNo, Object recDate, Object retTime, Object status, Object esbMsg, Object esbId, Object esbStatus, Object esbServiceCode, Object esbOut, Object esbIn, Object ybOut, Object ybIn) {
        Zjywpt_yg_trand_infos infos = new Zjywpt_yg_trand_infos();
        infos.setINTERFACENO(interFaceNo);
        infos.setRECDATE((String) recDate);
        infos.setRETDATE((String) retTime);
        infos.setSTATUS((String) status);
        infos.setESBMSG((String) esbMsg);
        infos.setESBID((String) esbId);
        infos.setESBSTATUS((String) esbStatus);
        infos.setESBServiceCode((String) esbServiceCode);
        infos.setESBOUT((String) esbOut);
        infos.setESBIN((String) esbIn);
        infos.setYBOUT((String) ybOut);
        infos.setYBIN((String) ybIn);
        //System.out.println(infos);
        trandMapper.addTrand(infos);
    }
}
